package com.zzwtec.androidtest;

import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Common {
    public static final String TAG = "AndroidTest";
    public static final String SO_INFO = "soInfo";

    public static boolean isMainThread() {
        return Thread.currentThread().getName().equals("main");
    }

    /**
     * 获取全部已加载的SO库
     */
    public static void getAllSOLoaded(){
        Map<String, String> allSOMap = null ;
        // 当前应用的进程ID
        int pid = android.os.Process.myPid();
        String path = "/proc/" + pid + "/maps";
        File file = new File(path);
        if(file.exists() && file.isFile()){
            allSOMap = readAppLoadSoLib(file.getAbsolutePath());
        } else {
            Log.e(TAG, "不存在[" + path + "]文件.");
        }

        StringBuilder sb = new StringBuilder();
        if(allSOMap!=null && !allSOMap.isEmpty()) {
            for (Map.Entry<String, String> entry : allSOMap.entrySet()) {
                sb.append(entry.getValue() + "\n");
            }
        }

        Log.e(TAG, sb.toString());
    }

    /**
     * 获取当前应用已加载的SO库
     */
    public static void getCurrApkSOLoaded(){
        Map<String, String> allSOMap = null ;
        // 当前应用的进程ID
        int pid = android.os.Process.myPid();
        String path = "/proc/" + pid + "/maps";
        File file = new File(path);
        if(file.exists() && file.isFile()){
            allSOMap = readAppLoadSoLib(file.getAbsolutePath());
        } else {
            Log.e(TAG, "不存在[" + path + "]文件.");
        }

        StringBuilder sb = new StringBuilder();
        if(allSOMap!=null && !allSOMap.isEmpty()) {
            for (Map.Entry<String, String> entry : allSOMap.entrySet()) {
                if(entry.getValue().startsWith("/data/app/")) {
                    sb.append(entry.getValue() + "\n");
                }
            }
        }
        Log.e(TAG, sb.toString());
    }

    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     */
    private static Map<String, String> readAppLoadSoLib(String fileName) {
        Map<String, String> allSOMap = new HashMap<>();
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                if(tempString.endsWith(".so")) {
                    int index = tempString.indexOf("/");
                    if(index != -1){
                        String str = tempString.substring(index);
                        // 所有so库（包括系统的，即包含/system/目录下的）
                        index = str.lastIndexOf("/");
                        String key = str.substring(index+1);
                        String value = str;
                        if(!allSOMap.containsKey(key)){
                            allSOMap.put(key, value);
                        }
                    }
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return allSOMap;
    }


    /**
     * 加载apk原包内的so库F
     * @param context
     * @param libName
     */
    public static void loadApkSoLib(Context context, String libName){
        if(libName.startsWith("lib") && libName.endsWith(".so")){
            loadPathSoLib(context.getApplicationInfo().nativeLibraryDir+ File.separator+libName);
        }else{
            loadPathSoLib(context.getApplicationInfo().nativeLibraryDir+ File.separator+"lib"+libName+".so");
        }
    }

    /**
     * 加载指定路径的so库
     * @param pathlib so库觉得路径
     */
    public static void loadPathSoLib(String pathlib){
        /**
         * 参考 http://blog.soliloquize.org/2015/01/06/Android动态替换so/
         *
         * 应用启动加载.so之后，同名的.so不能再次被加载。没有找到卸载.so的方法，因此在进行动态更新的时候需要在加载本地.so之前进行，否则不能加载成功。
         * 调用Activity的finish方法退出应用之后不能保证当前进程清理干净，因此最好退出的时候将自身进程结束。
         *
         * 在安卓下System.load只能加载两个目录路径下的so文件:
         * /system/lib ;
         * 安装包的路径，即：/data/data/<packagename>/…
         */
        System.load(pathlib);
    }
}
